package org.net.operation;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import com.info.dbase.Connections;
import com.info.dbase.ExecuteSql;
import com.info.server.Event;
import com.info.server.StartServer;
import com.info.threads.ExecuteThread;
import com.info.threads.TerPoolThread;
import com.info.utils.InfoPacket;
import com.info.utils.TimeTool;

/**
 * @author HAHA
 * 
 */
public class TerServer implements Runnable {
	private static Logger logger=Logger.getLogger(TerServer.class);
	private int port = 0;
	private String ip = null;
	private String code = "";
	public TerPoolThread manager = null;

	private ServerSocketChannel ssc = null;
	private Selector selector = null;
	public static Hashtable channelHash = new Hashtable();
	public static List<String> terList = null;
	public static Hashtable<String,Integer> terTable = null;
	private ExecuteSql execute = null;
	private ByteBuffer buffer = null;

	private ArrayList list = null;
	int i = 0;
	private String str = "";
	public long slecttime = 0L;
	private long startTime=0L;
	private boolean flag = true;
	private InetSocketAddress address = null;
	private ServerSocket ss = null;

	/**
	 * 初始网络设置
	 * @param port
	 * @param ip
	 * @param code
	 * @param manager
	 * @throws Exception
	 */
	public TerServer(int port, String ip, String code, TerPoolThread manager)
			throws Exception {
		this.port = port;
		this.ip = ip;
		this.code = code;
		this.manager = manager;
		this.buffer = ByteBuffer.allocateDirect(StartServer.GATE_RECV_BUFFER);
		initSocket();
	}

	/**
	 * 获取终端列表
	 * @return
	 * @throws Exception
	 */
	private List<String> getAllTerList() throws Exception {
		if (this.execute == null)
			this.execute = new ExecuteSql();
		List<String> terlist = new ArrayList<String>();
		Connection conn = null;
		ResultSet rs = null;
		Statement stmt = null;
		String sql = "SELECT TERMINAL FROM T_DEVICES";
		try {
			conn = Connections.getConnection();
			rs = this.execute.getRs(sql, conn,stmt);
			while (rs.next()) {
				terlist.add(rs.getString(1));
			}
		} catch (Exception e) {
				logger.info("初始化终端数据库处理出错" + e.getMessage());
				Connections.close(conn);
			e.printStackTrace();
		} finally {
			if (rs != null)
				rs.close();
			Connections.close(conn);
		}
		return terlist;
	}
	
	/**
	 * 获取终端上传时间间隔参数
	 * @return
	 * @throws Exception
	 */
	private Hashtable<String,Integer> getAllTerTable() throws Exception {
		if (this.execute == null)
			this.execute = new ExecuteSql();
		Hashtable<String,Integer> terTableTemp=new Hashtable<String, Integer>();
		Connection conn = null;
		ResultSet rs = null;
		Statement stmt = null;
		String sql = "SELECT TERMINAL,UPTIME FROM T_DEVICES";
		try {
			conn = Connections.getConnection();
			rs = this.execute.getRs(sql, conn,stmt);
			while (rs.next()) {
				terTableTemp.put(rs.getString(1),rs.getInt(2));
				ExecuteThread.runtimeLALO.put(rs.getString(1), new BigDecimal(0));
			}
		} catch (Exception e) {
				logger.info("获取终端参数数据库处理出错" + e.getMessage());
				Connections.close(conn);
			e.printStackTrace();
		} finally {
			if (rs != null)
				rs.close();
			Connections.close(conn);
		}
		return terTableTemp;
	}

	/**
	 * 打开socket
	 * @throws Exception
	 */
	public void initSocket() throws Exception {
			logger.info("SHW#初始化终端服务监听器");
		this.selector = Selector.open();
		this.ssc = ServerSocketChannel.open();
		this.ssc.configureBlocking(false);
			logger.info("SHW#初始ServerSocketChannel成功");

		this.ss = this.ssc.socket();
		this.address = new InetSocketAddress(this.port);
		this.ss.bind(this.address);
			logger.info("SHW#绑定端口:" + this.port + ",成功");
		this.ssc.register(this.selector, 16);
		this.slecttime = System.currentTimeMillis();
		this.startTime =System.currentTimeMillis();
		logger.info("SHW#初始化终端服务监听器成功"+TimeTool.getDateTimeSecond());
		logger.info("SHW#准备初始化注册终端 ");
		try {
			terList = getAllTerList();
			terTable=getAllTerTable();
			logger.info("SHW#初始化注册终端个数 ：" + terList.size());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void createSocket() {
		try {
			try {
				Thread.sleep(3000L);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			logger.info("SHW#重新建立终端服务监听器  "+TimeTool.getDateTimeSecond());
			if (channelHash != null) {
				InfoPacket object = null;
				try {
					Collection s = channelHash.values();
					Iterator iter = s.iterator();
					for (int i = 0; iter.hasNext(); i++) {
						object = (InfoPacket) iter.next();
						if (object != null)
							object.closeChannel();
					}
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				channelHash.clear();
				logger.info("SHW#移除所有保存的连接");
			}
			this.ss.close();
			this.ssc.close();
			this.selector.wakeup();
			this.selector.close();
			logger.info("SHW#关闭监听器");

			if ((TerPoolThread.msgList != null)
					&& (TerPoolThread.msgList.size() > 1000)) {
				TerPoolThread.msgList.clear();
				System.gc();
			}
			logger.info("SHW#移除所有事件");
			initSocket();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	public void run() {
		int n = 0;
		while (this.flag) {
			try {
				n = this.selector.select(100000L);
			} catch (Exception e) {
				return;
			}
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}

			try {
				if (n > 0) {
					Iterator it = this.selector.selectedKeys().iterator();
					while (it.hasNext()) {
						SelectionKey key = (SelectionKey) it.next();

						if (!key.isValid()) {
							it.remove();
						} else {
							this.slecttime = System.currentTimeMillis();
							try {
								if (key.isAcceptable())
									doAcceptable(key);
								else if (key.isReadable())
									doReadable(key);
							} catch (IOException e1) {
								try {
									InfoPacket channelPack = (InfoPacket) key
											.attachment();
									channelPack.closeChannel();
									key.cancel();
									if (channelHash != null)
										channelHash.remove(channelPack);
								} catch (Exception ie) {
									ie.printStackTrace();
								}
							} catch (Exception ex) {
								ex.printStackTrace();
								try {
									InfoPacket channelPack = (InfoPacket) key
											.attachment();
									channelPack.closeChannel();
									key.cancel();
									if (channelHash != null)
										channelHash.remove(channelPack);
								} catch (Exception ie) {
									ie.printStackTrace();
								}
							}
							it.remove();
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void doAcceptable(SelectionKey key) throws Exception {
		if ((channelHash != null) && (channelHash.size() < StartServer.conSum)) {
			ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

			if (ssc == null) {
				logger.info("SHW#终端监听连接的ServerSocketChannel为空!");
			}

			SocketChannel sc = ssc.accept();

			if (sc == null) {
				if (StartServer.logFlag) {
					logger.info("SHW#终端连接的SocketChannel为空!");
				}
				key.cancel();
			} else {
				sc.configureBlocking(false);

				if (StartServer.logFlag) {
					logger.info("SHW#终端服务线程接收一个新的连接，正准备生成拆组包对象");
				}

				InfoPacket channelPack = new InfoPacket();

				sc.register(this.selector, 1, channelPack);

				Socket socket = sc.socket();

				if (socket == null) {
					logger.info("SHW#终端新连接的Socket对象为空！");
				}

				socket.setReceiveBufferSize(StartServer.GATE_RECV_BUFFER);
				socket.setSendBufferSize(StartServer.SEND_BUF);

				channelPack.setSecurity(this.selector, sc);

				channelPack.updateTime = System.currentTimeMillis();
				channelPack.createTime = System.currentTimeMillis();

				logger.info("SHW#终端新连接的地址:"
						+ socket.getRemoteSocketAddress());
			}
		} else {
			clearTimeout();
			logger.info("SHW#连接网关的数量已经超过了允许的" + StartServer.conSum
					+ "个连接容量");
		}
	}

	public void doReadable(SelectionKey key) throws Exception {
		SocketChannel sc = (SocketChannel) key.channel();
		InfoPacket channelPack = (InfoPacket) key.attachment();
		this.buffer.clear();
		if ((channelPack == null) || (sc.read(this.buffer) <= 0)) {
			throw new IOException("终端连接的通道出现异常，连接关闭!");
		}
		this.str = channelPack.uppacket(this.buffer);
		if ((this.str == null) || (this.str.equals("")))
			return;
		channelPack.updateTime = System.currentTimeMillis();
		channelPack.extPacket(this.str);
		this.list = channelPack.getMsg_Str();
		if ((this.list != null) && (this.list.size() > 0)) {
			this.i = 0;
			int size = this.list.size();
			while (this.i < size) {
				this.str = ((String) this.list.get(this.i));
				Event msg = new Event();
				msg.setMsgInfo(this.str);
				msg.setUppack(channelPack);
				this.manager.process(msg);
				this.i += 1;
			}
		}
	}

	public void clearTimeout() {
		long times = System.currentTimeMillis();
		if (this.selector == null) {
			createSocket();
			return;
		}
		if (times - this.slecttime > StartServer.timequit) {
			logger.info("SHW#长时间未更新，重新建立终端监听服务");
			createSocket();
			return;
		}
		
		if(times-this.startTime>StartServer.gameOver){
			logger.info("SHW#24小时刷新初始化终端服务");
//			createSocket();
			try {
				terList = getAllTerList();
				terTable= getAllTerTable();
				logger.info("SHW#初始化注册终端个数 ：" + terList.size());
			} catch (Exception e) {
				e.printStackTrace();
			}
			return;
		}
		long time = System.currentTimeMillis();

		Set set = this.selector.keys();
		if(set.size()>1)
		logger.info("SHW#移除过期终端执行,通道中总共" + (set.size() - 1)
				+ "个连接,其中" + channelHash.size() + "个合法连接");
		// 通道中的总连接
		Iterator it = set.iterator();
		InfoPacket object = null;
		while (it.hasNext()) {
			SelectionKey key = (SelectionKey) it.next();
			object = (InfoPacket) key.attachment();
			if (object != null) {
				if (object.getType().equals("2")) {
					if (time - object.updateTime > StartServer.overTime) {
						try {
							object.closeChannel();
							key.cancel();
						} catch (Exception e1) {
							e1.printStackTrace();
						}
					}
				} else {
					if (time - object.createTime > StartServer.terTimeQuit) {
						try {
							object.closeChannel();
							key.cancel();
						} catch (Exception e1) {
							e1.printStackTrace();
						}
					}
				}
			}
		}
		// 通道中的合法连接
		object = null;
		time = System.currentTimeMillis();
		if (channelHash == null) {
			channelHash = new Hashtable();
		}
		Collection s = channelHash.values();
		Iterator iter = s.iterator();
		for (int i = 0; iter.hasNext(); i++) {
			object = (InfoPacket) iter.next();
			if (object != null) {
				if (object.getType().equals("2")) {
					if (time - object.updateTime > StartServer.overTime) {
						try {
							object.closeChannel();
							iter.remove();
						} catch (Exception e1) {
							e1.printStackTrace();
						}

					}
				} else {
					if (time - object.createTime > StartServer.terTimeQuit) {
						try {
							object.closeChannel();
							iter.remove();
						} catch (Exception e1) {
							e1.printStackTrace();
						}
					}
				}
			} else {
				try {
					iter.remove();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		}
	}
}